package by

import (
	"errors"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"io"
	"net/http"
	"save-kindle/entity"
	"save-kindle/log"
	"save-kindle/source"
	"save-kindle/util"
	"strings"
	"time"
)

type BaYiBook struct {
	source.BookInfo
	Catalog []entity.Article
}

// GetCatalog 获取文章目录
func (book *BaYiBook) GetCatalog() ([]entity.Article, error) {
	start := time.Now()
	log.Println(start.Format("2006-01-02 15:04:05.000"))

	catalogUrl := fmt.Sprintf("%s/book/%s/", book.WebSite, book.BookId)
	request, err := http.NewRequest("GET", catalogUrl, nil)
	if err != nil {
		log.PrintErr(err)
		return nil, err
	}

	resp, err := http.DefaultClient.Do(request)

	defer resp.Body.Close()

	respInfo, err := io.ReadAll(resp.Body)
	if err != nil {
		log.PrintErr(err)
		return nil, err
	}

	respStr := util.DecoderConvertBytes(respInfo)
	document, err := goquery.NewDocumentFromReader(strings.NewReader(respStr))
	if err != nil {
		log.PrintErr(err)
		return nil, err
	}

	book.Catalog = make([]entity.Article, 0)

	document.Find("#list").Each(func(i int, selection *goquery.Selection) {
		selection.Find("dd").Each(func(ii int, ddTag *goquery.Selection) {
			attr, exists := ddTag.Find("a").Attr("href")
			if exists {
				article := entity.Article{
					ArticleUrl:  attr,
					ArticleName: ddTag.Text(),
				}
				book.Catalog = append(book.Catalog, article)
			}
		})
	})

	end := time.Now()
	log.Println(end.Sub(start), end.Format("2006-01-02 15:04:05.000"))
	return book.Catalog, nil
}

// GetArticleContent 获取文章内容
func (book *BaYiBook) GetArticleContent(article entity.Article) (entity.Article, error) {
	retryCount := 0
retry:
	if retryCount > 1000 {
		log.PrintErr(article.ArticleUrl, article.ArticleName, "重试失败")
		return article, errors.New("重试失败")
	}
	request, _ := http.NewRequest("GET", fmt.Sprintf("%s%s", book.WebSite, article.ArticleUrl), nil)
	resp, err := http.DefaultClient.Do(request)
	if err != nil {
		log.PrintErr(err.Error())
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		time.Sleep(1 * time.Second)
		log.PrintErr("retry", article)
		retryCount++
		goto retry
	}

	respInfo, err := io.ReadAll(resp.Body)
	if err != nil {
		log.PrintErr(err)
	}

	respStr := util.DecoderConvertBytes(respInfo)
	document, err := goquery.NewDocumentFromReader(strings.NewReader(respStr))
	if err != nil {
		log.PrintErr(err)
	}

	document.Find("#content").Each(func(i int, selection *goquery.Selection) {
		html, _ := selection.Html()
		html = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(html, " ", ""), "<br/>", "\n"), "\n\n", "\n")

		// 替换掉内容开头的\n
		for {
			index := strings.Index(html, "\n")
			if index == 0 {
				html = strings.Replace(html, "\n", "", 1)
			} else {
				break
			}

		}
		// 添加文章内容
		article.ArticleContent = html
	})

	if article.ArticleContent == "" || strings.Contains(article.ArticleContent, "章节内容正在手打中，请稍等片刻，内容更新后，请重新刷新页面") {
		// 暂停1s进行重试
		//log.PrintErr("retry", article)
		time.Sleep(1 * time.Second)
		retryCount++
		goto retry
	}
	return article, nil
}
